/**
 * Copyright(C),2015 misaka15842
 * @author misaka15842 (misakamoe@yahoo.com)
 *
 * Draw.h 包含常用的几何类型和像素类型的定义
 */

#ifndef DRAW_H_
#define DRAW_H_

#include <cstdint>
#include <utility>

namespace misaka
{
    struct RGBAPixel
    {
        uint8_t r, g, b, a;
    };

    template<typename OffsetTp>
    struct Point
    {
        OffsetTp x, y;
        Point(OffsetTp _x = 0, OffsetTp _y = 0) noexcept :
            x(_x), y(_y) {}

        template<typename Tp>
            Point(const Point<Tp>& p) noexcept:
                x(p.x), y(p.y) { }
    };

    /* WARNING: 各 operator+/- 可能出现算术溢出，未作任何检查 */

    template<typename OffsetTp>
    struct Vector
    {
        OffsetTp x, y;
        Vector(OffsetTp _x = 0, OffsetTp _y = 0) noexcept :
            x(_x), y(_y){}

        template<typename Tp>
            explicit Vector(const Vector<Tp>& v) noexcept :
                x(v.x), y(v.y){}

        /* NOTE: using c++ 14 feature */
        template<typename Tp>
        auto operator+(const Vector<Tp>& v) noexcept -> decltype(v.x + this->x)
        {
            return Vector(x + v.x, y + v.y);
        }
        template<typename Tp>
        auto operator-(const Vector<Tp>& v) noexcept -> decltype(v.x - this->x)
        {
            return Vector(x - v.x, y - v.y);
        }
    };

    template<typename Tp1, typename Tp2>
        auto operator+(const Point<Tp1>& p, const Vector<Tp2>& v) noexcept -> Point < decltype(std::declval<Tp1>() + std::declval<Tp2>()) >
    {
        return Point < decltype(std::declval<Tp1>() + std::declval<Tp2>()) > (p.x + v.x, p.y + v.y);
    }

    template<typename Tp1, typename Tp2>
        auto operator-(const Point<Tp1>& p, const Vector<Tp2>& v) noexcept -> Point < decltype(std::declval<Tp1>() - std::declval<Tp2>()) >
    {
        return Point < decltype(std::declval<Tp1>() - std::declval<Tp2>()) > (p.x - v.x, p.y - v.y);
    }


    template<typename OffsetTp>
    struct Rectangular
    {
        OffsetTp x,y,w,h;
        Rectangular(OffsetTp _x = OffsetTp(0),OffsetTp _y = OffsetTp(0),OffsetTp _w = OffsetTp(0),OffsetTp _h = OffsetTp(0)):
            x(_x),y(_y),w(_w),h(_h){}

        template<typename Tp>
        Rectangular(const Rectangular<Tp>& rhs):
            x(rhs.x),y(rhs.y),w(rhs.w),h(rhs.h){}
    };
}

#endif //DRAW_H_
